#!/usr/bin/python3
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: t -*-

import os
import sys
import time
import glob
import mrget
import shutil
import subprocess
import robust_layer.simple_git
import mirrors.plugin


class Main:

    def __init__(self, sock):
        self.sock = sock
        self.dataDir = mirrors.plugin.params["storage-file"]["data-directory"]
        self.repoDirDatabase = os.path.join(self.dataDir, ".iptv-org-database.git")
        self.repoDirStreams = os.path.join(self.dataDir, ".iptv-org-streams.git")
        self.repoDirGuides = os.path.join(self.dataDir, ".iptv-org-guides.git")
        self.jsonTmpDir = os.path.join(self.dataDir, ".json-files")
        self.p = InfoPrinter()
        self.progress = 0

    def run(self):
        # from https://github.com/iptv-org/api
        jsonFileList = [
            "channels.json",
            "streams.json",
            "guides.json",
            "categories.json",
            "languages.json",
            "subdivisions.json",
            "regions.json",
            "blocklist.json",
        ]

        # download iptv database
        url = mrget.target_urls("mirror://github/iptv-org/database")[0]
        self.p.print("Updating repository from %s" % (url))
        robust_layer.simple_git.pull(self.repoDirDatabase, reclone_on_failure=True, url=url)

        # download iptv streams
        url = mrget.target_urls("mirror://github/iptv-org/iptv")[0]
        self.p.print("Updating repository from %s" % (url))
        robust_layer.simple_git.pull(self.repoDirStreams, reclone_on_failure=True, url=url)

        # download iptv guides
        url = mrget.target_urls("mirror://github/iptv-org/epg")[0]
        self.p.print("Updating repository from %s" % (url))
        robust_layer.simple_git.pull(self.repoDirGuides, reclone_on_failure=True, url=url)

        # download json files
        url = "https://iptv-org.github.io/api"
        Util.forceMakeDir(self.jsonTmpDir)
        for fn in jsonFileList:
            self.__downloadFile(os.path.join(url, fn), os.path.join(self.jsonTmpDir, fn))

        # check json files
        if True:
            # FIXME
            pass

        # swap json files
        for fullfn in glob.glob(os.path.join(self.dataDir, "*.json")):
            Util.forceDelete(fullfn)
        for fullfn in glob.glob(os.path.join(self.jsonTmpDir, "*.json")):
            shutil.move(fullfn, self.dataDir)
        Util.forceDelete(self.jsonTmpDir)

    def __downloadFile(self, url, localFile):
        while True:
            try:
                subprocess.check_call(["wget", "--quiet", "--no-check-certificate", "-O", localFile, url])      # always re-dowloand
                break
            except subprocess.CalledProcessError as e:
                if e.returncode == 8:       # not found
                    raise
                self.p.print("download failed and try again: %s" % str(e))
                time.sleep(60)


class InfoPrinter:

    def __init__(self):
        self.indent = 0

    def incIndent(self):
        self.indent = self.indent + 1

    def decIndent(self):
        assert self.indent > 0
        self.indent = self.indent - 1

    def print(self, s):
        line = ""
        line += "\t" * self.indent
        line += s
        print(line)


class Util:

    @staticmethod
    def forceDelete(path):
        if os.path.islink(path):
            os.remove(path)
        elif os.path.isfile(path):
            os.remove(path)
        elif os.path.isdir(path):
            shutil.rmtree(path)
        elif os.path.lexists(path):
            os.remove(path)             # other type of file, such as device node
        else:
            pass                        # path does not exist, do nothing

    @staticmethod
    def forceMakeDir(path):
        Util.forceDelete(path)
        os.mkdir(path)


###############################################################################

if __name__ == "__main__":
    with mirrors.plugin.ApiClient() as sock:
        try:
            Main(sock).run()
            sock.progress_changed(100)
        except Exception:
            sock.error_occured(sys.exc_info())
            raise
